import { useState } from "react";

interface StateProps<D> {
  data: D | null;
  error: Error | null;
  stat: "idle" | "error" | "loading" | "success";
}

const defaultInitialState: StateProps<null> = {
  data: null,
  error: null,
  stat: "idle",
};

const defaultConfig = {
  throwOnError: false,
};

/**
 * 处理异步状态的hook
 * @param { Type } D
 * @param  { StateProps<D> } initialState
 * @return {*}
 */
export const useAsync = <D>(
  initialState?: StateProps<D>,
  initialConfig?: typeof defaultConfig
) => {
  const config = { ...defaultConfig, ...initialConfig };
  const [state, setState] = useState<StateProps<D>>({
    ...initialState,
    ...defaultInitialState,
  });
  const setData = (data: D | null) => {
    setState({
      data,
      error: null,
      stat: "success",
    });
  };

  const setLoading = () => {
    setState({
      ...state,
      stat: "loading",
    });
  };
  const setError = (error: Error) => {
    setState({
      error,
      data: null,
      stat: "error",
    });
  };

  const run = (promise: Promise<D | null>) => {
    if (!promise || !promise.then) throw new Error("请传入Promise类型");
    setLoading();
    return promise
      .then((data) => {
        setData(data);
        return data;
      })
      .catch((error) => {
        setError(error);
        if (config.throwOnError) return Promise.reject(error);
        return error;
      });
  };

  return {
    isIdle: state.stat === "idle",
    isError: state.stat === "error",
    isLoading: state.stat === "loading",
    isSuccess: state.stat === "success",
    setData,
    setLoading,
    setError,
    run,
    ...state,
  };
};
